﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using T3D = Tekla.Structures.Geometry3d;
using TSM = Tekla.Structures.Model;

namespace TelaOpenTool.ModelTool
{
    public class BeamTool
    {
        public BeamTool() { }



        /// <summary>
        /// 创建钢梁
        /// </summary>
        /// <param name="steelBeamData">钢梁数据</param>
        /// <returns></returns>
        public static bool CreateSteelBeam(Data.SteelBeamData steelBeamData)
        {
            try
            {
                if (!new TSM.Model().GetConnectionStatus())
                {
                    return false;
                }

                T3D.Point point = steelBeamData.StartPoint;
                T3D.Point point2 = steelBeamData.EndPoint;
                TSM.Beam beam = new TSM.Beam();
                beam.StartPoint = point;
                beam.EndPoint = point2;
                beam.Profile.ProfileString = steelBeamData.Profile;
                beam.Finish = "PAINT";
                beam.Material.MaterialString = steelBeamData.Material;
                beam.Class = "5";
                bool result = false;
                result = beam.Insert();

                new TSM.Model().CommitChanges();
                return result;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 创建钢柱
        /// </summary>
        /// <param name="steelColumnData"></param>
        /// <returns></returns>
        public static bool CreateSteelColumn(Data.SteelColumnData steelColumnData)
        {
            try
            {
                if (!new TSM.Model().GetConnectionStatus())
                {
                    return false;
                }

                T3D.Point point = steelColumnData.StartPoint;
                T3D.Point point2 = steelColumnData.EndPoint;
                TSM.Beam beam = new TSM.Beam();
                beam.StartPoint = point;
                beam.EndPoint = point2;
                beam.Profile.ProfileString = steelColumnData.Profile;
                beam.Finish = "PAINT";
                beam.Material.MaterialString = steelColumnData.Material;
                beam.Class = "5";
                bool result = false;
                result = beam.Insert();

                new TSM.Model().CommitChanges();
                return result;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 创建连接节点
        /// </summary>
        /// <returns></returns>
        public static bool CreateConnection()
        {
            try
            {
                TSM.Beam B1 = new TSM.Beam(new T3D.Point(15000, 0, -500), new T3D.Point(15000, 0, 6000));
                B1.Profile.ProfileString = "HN400*200*8*13";
                B1.Material.MaterialString = "Q235B";

                TSM.Beam B2 = new TSM.Beam(new T3D.Point(15000, 0, 0), new T3D.Point(18000, 0, 0));
                B2.Profile.ProfileString = "HN400*200*8*13";
                B2.Material.MaterialString = "Q235B";

                B1.Insert();
                B2.Insert();

                TSM.Connection C = new TSM.Connection();
                C.Name = "Test End Plate";
                C.Number = 144;
                C.LoadAttributesFromFile("standard");
                C.UpVector = new T3D.Vector(0, 0, 1000);
                C.PositionType = Tekla.Structures.PositionTypeEnum.COLLISION_PLANE;

                C.SetPrimaryObject(B1);
                C.SetSecondaryObject(B2);

                C.SetAttribute("e2", 10.0);
                C.SetAttribute("e1", 10.0);

                C.Insert();

                new TSM.Model().CommitChanges();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 创建螺栓
        /// </summary>
        public static void CreateBolt()
        {
            try
            {
                TSM.ContourPlate cp = new TSM.ContourPlate();
                cp.AddContourPoint(new TSM.ContourPoint(new T3D.Point(0, 0, 0), null));
                cp.AddContourPoint(new TSM.ContourPoint(new T3D.Point(0, 1000, 0), null));
                cp.AddContourPoint(new TSM.ContourPoint(new T3D.Point(1000, 1000, 0), null));
                cp.AddContourPoint(new TSM.ContourPoint(new T3D.Point(1000, 0, 0), null));
                cp.Profile.ProfileString = "PL50";
                cp.Material.MaterialString = "Q235B";
                bool cpResult = cp.Insert();

                TSM.BoltXYList B = new TSM.BoltXYList();

                B.PartToBeBolted = cp;
                B.PartToBoltTo = cp;

                B.FirstPosition = new T3D.Point(0, 0, 0);
                B.SecondPosition = new T3D.Point(100, 0, 0);

                // 螺栓直径
                B.BoltSize = 16;
                B.Tolerance = 3.00;
                // 螺栓等级
                B.BoltStandard = "B";
                B.BoltType = TSM.BoltGroup.BoltTypeEnum.BOLT_TYPE_WORKSHOP;
                B.CutLength = 105;

                // 长度
                B.Length = 50;
                B.ExtraLength = 15;
                B.ThreadInMaterial = TSM.BoltGroup.BoltThreadInMaterialEnum.THREAD_IN_MATERIAL_NO;

                B.Position.Depth = TSM.Position.DepthEnum.MIDDLE;
                B.Position.Plane = TSM.Position.PlaneEnum.MIDDLE;
                B.Position.Rotation = TSM.Position.RotationEnum.FRONT;

                B.Bolt = true;
                B.Washer1 = true;
                B.Washer2 = true;
                B.Washer3 = true;
                B.Nut1 = true;
                B.Nut2 = true;

                B.Hole1 = true;
                B.Hole2 = true;
                B.Hole3 = true;
                B.Hole4 = true;
                B.Hole5 = true;

                B.AddBoltDistX(100);
                B.AddBoltDistX(200);
                B.AddBoltDistX(300);

                B.AddBoltDistY(100);
                B.AddBoltDistY(200);
                B.AddBoltDistY(300);

                //   TSM.PourObject pourObj = B.GetFatherPour();

                bool BResult = B.Insert();
                new TSM.Model().CommitChanges();
            }
            catch (Exception)
            {
            }
        }


        /// <summary>
        /// 镜像对象
        /// </summary>
        /// <param name="mirrorLine">需要镜像的对象</param>
        /// <param name="part">对称轴</param>
        public static bool MirrorPart(TSM.ModelObject part, T3D.Line mirrorLine)
        {
            try
            {
                if (part == null || mirrorLine == null)
                {
                    return false;
                }

                var model = new TSM.Model();

                if (!model.GetConnectionStatus())
                {
                    return false;
                }

                // 保存当前工作平面
                var currentPlane = model.GetWorkPlaneHandler().GetCurrentTransformationPlane();
                // 将模型设置全局坐标系
                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(new TSM.TransformationPlane());
                model.CommitChanges();
                part.Select();


                T3D.CoordinateSystem globalCoord = new T3D.CoordinateSystem()
                {
                    Origin = new T3D.Point(),
                    AxisX = new T3D.Vector(1, 0, 0),
                    AxisY = new T3D.Vector(0, 1, 0),
                };

                T3D.Vector zVetor = new T3D.Vector(0, 0, 1);
                T3D.Vector y_vector = mirrorLine.Direction.GetNormal();

                T3D.Vector x_vector_1 = y_vector.Cross(zVetor).GetNormal();
                T3D.Vector x_vector_2 = y_vector.Cross(zVetor).GetNormal() * -1;

                // 镜像原点
                T3D.Point origin = new T3D.Point();
                T3D.Point project = T3D.Projection.PointToLine(origin, mirrorLine);
                T3D.Point mirrorPoint = new T3D.Point(2 * project.X - origin.X,
                                                       2 * project.Y - origin.Y,
                                                       2 * project.Z - origin.Z);

                T3D.CoordinateSystem left_coord = new T3D.CoordinateSystem()
                {
                    Origin = new T3D.Point(),
                    AxisX = x_vector_1,
                    AxisY = y_vector,
                };

                T3D.CoordinateSystem right_coord = new T3D.CoordinateSystem()
                {
                    Origin = mirrorPoint,
                    AxisX = x_vector_2,
                    AxisY = y_vector,
                };

                var mirrorPart = Tekla.Structures.Model.Operations.Operation.CopyObject(part, left_coord, right_coord);

                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(currentPlane);
                model.CommitChanges();

                return mirrorPart != null;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 混凝土板
        /// </summary>
        /// <returns></returns>
        public static bool CreatePlateWithRebar()
        {
            try
            {
                TSM.Model model = new TSM.Model();
                var currentPlane = model.GetWorkPlaneHandler().GetCurrentTransformationPlane();
                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(new TSM.TransformationPlane());
                model.CommitChanges();

                double length = 3000;
                double width = 2000;

                TSM.ContourPlate plate = new TSM.ContourPlate();
                plate.Contour.AddContourPoint(new TSM.ContourPoint(new T3D.Point(), null));
                plate.Contour.AddContourPoint(new TSM.ContourPoint(new T3D.Point(length, 0, 0), null));
                plate.Contour.AddContourPoint(new TSM.ContourPoint(new T3D.Point(length, width, 0), null));
                plate.Contour.AddContourPoint(new TSM.ContourPoint(new T3D.Point(0, width, 0), null));

                plate.Class = "3";
                plate.Material.MaterialString = "C30";
                plate.Profile.ProfileString = "60";
                plate.PartNumber = new TSM.NumberingSeries("P", 1);
                plate.AssemblyNumber = new TSM.NumberingSeries("P", 1);
                plate.Name = "PCB-1";

                plate.Position.Depth = TSM.Position.DepthEnum.BEHIND;

                plate.Insert();

                InsertPlateRebars(plate, length, width, 60);

                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(currentPlane);
                model.CommitChanges();
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }


        private static bool InsertPlateRebars(TSM.ContourPlate plate, double length, double width, double thick)
        {
            try
            {
                TSM.Model model = new TSM.Model();

                plate.Select();

                TSM.RebarGroup horRebars = new TSM.RebarGroup();
                horRebars.Class = 8;
                horRebars.Polygons = new System.Collections.ArrayList();

                TSM.Polygon horRebar_PL1 = new TSM.Polygon();
                TSM.Polygon horRebar_PL2 = new TSM.Polygon();
                horRebar_PL1.Points.Add(new T3D.Point(0, 50, -thick + 15));
                horRebar_PL1.Points.Add(new T3D.Point(length - 50, 50, -thick + 15));
                horRebar_PL2.Points.Add(new T3D.Point(0, width - 50, -thick + 15));
                horRebar_PL2.Points.Add(new T3D.Point(length - 50, width - 50, -thick + 15));

                horRebars.Polygons.Add(horRebar_PL1);
                horRebars.Polygons.Add(horRebar_PL2);

                horRebars.Grade = "HRB400";
                horRebars.RadiusValues = new System.Collections.ArrayList() { 16.0 };

                horRebars.Name = "R";
                horRebars.NumberingSeries = new TSM.NumberingSeries("R", 1);

                horRebars.Size = "8";
                horRebars.Spacings = new System.Collections.ArrayList() { 200.0 };
                horRebars.SpacingType = TSM.BaseRebarGroup.RebarGroupSpacingTypeEnum.SPACING_TYPE_EXACT_SPACE_FLEX_AT_MIDDLE;
                horRebars.StartHook.Shape = TSM.RebarHookData.RebarHookShapeEnum.NO_HOOK;
                horRebars.EndHook.Shape = TSM.RebarHookData.RebarHookShapeEnum.NO_HOOK;
                horRebars.StartPointOffsetValue = -90.0;
                horRebars.EndPointOffsetValue = -90.0;
                horRebars.StartPointOffsetType = TSM.Reinforcement.RebarOffsetTypeEnum.OFFSET_TYPE_COVER_THICKNESS;
                horRebars.EndPointOffsetType = TSM.Reinforcement.RebarOffsetTypeEnum.OFFSET_TYPE_COVER_THICKNESS;

                horRebars.Father = plate;

                horRebars.Insert();

                model.CommitChanges();
                return false;
            }
            catch (Exception)
            {
                return false;
            }
        }


        /// <summary>
        /// 混凝土梁
        /// </summary>
        /// <returns></returns>
        public static bool CreatePreBeam(T3D.Point startP, T3D.Point endP)
        {
            try
            {
                TSM.Model model = new TSM.Model();
                var currentPlane = model.GetWorkPlaneHandler().GetCurrentTransformationPlane();
                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(new TSM.TransformationPlane());
                model.CommitChanges();

                TSM.Beam beam = new TSM.Beam();

                beam.StartPoint = startP;
                beam.EndPoint = endP;

                beam.Name = "beam";
                beam.Profile.ProfileString = "800*200";
                beam.Material.MaterialString = "C30";
                beam.Class = "6";
                beam.PartNumber = new TSM.NumberingSeries("pc", 1);
                beam.AssemblyNumber = new TSM.NumberingSeries("pc", 1);


                beam.Position.Depth = TSM.Position.DepthEnum.BEHIND;
                beam.Position.Plane = TSM.Position.PlaneEnum.MIDDLE;
                beam.Position.Rotation = TSM.Position.RotationEnum.TOP;

                beam.CastUnitType = TSM.Part.CastUnitTypeEnum.PRECAST;

                beam.Insert();

                CutBeam(beam);

                var localCoord = BeamLocalCoord(beam);

                // 生成钢筋
                BeamGj(beam, localCoord);

                Beam_LongRebar(beam, localCoord);

                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(currentPlane);
                model.CommitChanges();

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        private static bool CutBeam(TSM.Beam beam)
        {
            try
            {
                TSM.Model model = new TSM.Model();

                TSM.Beam cutBeam = new TSM.Beam();
                cutBeam.Profile.ProfileString = "150*200";
                cutBeam.StartPoint = beam.StartPoint;
                cutBeam.EndPoint = beam.EndPoint;

                cutBeam.Position.Depth = TSM.Position.DepthEnum.BEHIND;
                cutBeam.Position.Plane = TSM.Position.PlaneEnum.MIDDLE;
                cutBeam.Position.Rotation = TSM.Position.RotationEnum.TOP;
                cutBeam.Class = TSM.BooleanPart.BooleanOperativeClassName;
                cutBeam.Insert();

                var boolPart = new TSM.BooleanPart();
                boolPart.Father = beam;
                boolPart.SetOperativePart(cutBeam);
                boolPart.Type = TSM.BooleanPart.BooleanTypeEnum.BOOLEAN_CUT;
                boolPart.Insert();

                //   beam.Modify();

                cutBeam.Delete();

                model.CommitChanges();

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }


        private static void BeamGj(TSM.Beam beam, T3D.CoordinateSystem localCoord)
        {
            try
            {
                double rebarSpace = 200.0;
                double rebarSize = 8.0;

                TSM.Model model = new TSM.Model();
                var currentPlane = model.GetWorkPlaneHandler().GetCurrentTransformationPlane();
                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(new TSM.TransformationPlane());
                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(new TSM.TransformationPlane(localCoord));
                model.CommitChanges();
                beam.Select();


                var minPoint = beam.GetSolid().MinimumPoint;
                var maxPoint = beam.GetSolid().MaximumPoint;

                var startP = beam.StartPoint;
                var endP = beam.EndPoint;

                double dx = maxPoint.X - minPoint.X; // 宽
                double dz = maxPoint.Z - minPoint.Z; // 高
                double dy = maxPoint.Y - minPoint.Y; // 长

                double coverThick = 20;

                TSM.Polygon horRebar_PL1 = new TSM.Polygon();
                T3D.Point pL1_p1 = new T3D.Point(startP.X + coverThick, maxPoint.Y - coverThick, minPoint.Z + coverThick);
                T3D.Point pL1_p2 = new T3D.Point(startP.X + coverThick, maxPoint.Y - coverThick, endP.Z - coverThick);
                T3D.Point pL1_p3 = new T3D.Point(startP.X + coverThick, minPoint.Y + coverThick, endP.Z - coverThick);
                T3D.Point pL1_p4 = new T3D.Point(startP.X + coverThick, minPoint.Y + coverThick, minPoint.Z + coverThick);
                horRebar_PL1.Points.Add(pL1_p1);
                horRebar_PL1.Points.Add(pL1_p2);
                horRebar_PL1.Points.Add(pL1_p3);
                horRebar_PL1.Points.Add(pL1_p4);
                horRebar_PL1.Points.Add(pL1_p1);


                TSM.Polygon horRebar_PL2 = new TSM.Polygon();
                T3D.Point pL2_p1 = new T3D.Point(endP.X - coverThick, maxPoint.Y - coverThick, minPoint.Z + coverThick);
                T3D.Point pL2_p2 = new T3D.Point(endP.X - coverThick, maxPoint.Y - coverThick, endP.Z - coverThick);
                T3D.Point pL2_p3 = new T3D.Point(endP.X - coverThick, minPoint.Y + coverThick, endP.Z - coverThick);
                T3D.Point pL2_p4 = new T3D.Point(endP.X - coverThick, minPoint.Y + coverThick, minPoint.Z + coverThick);
                horRebar_PL2.Points.Add(pL2_p1);
                horRebar_PL2.Points.Add(pL2_p2);
                horRebar_PL2.Points.Add(pL2_p3);
                horRebar_PL2.Points.Add(pL2_p4);
                horRebar_PL2.Points.Add(pL2_p1);


                TSM.RebarGroup gjRebars = new TSM.RebarGroup();
                gjRebars.Class = 8;
                gjRebars.Polygons = new System.Collections.ArrayList();
                gjRebars.Polygons.Add(horRebar_PL1);
                gjRebars.Polygons.Add(horRebar_PL2);

                gjRebars.Grade = "HRB400";
                gjRebars.RadiusValues = new System.Collections.ArrayList() { 16.0 };

                gjRebars.Name = "R";
                gjRebars.NumberingSeries = new TSM.NumberingSeries("R", 1);

                gjRebars.Size = "8";
                gjRebars.Spacings = new System.Collections.ArrayList() { rebarSpace };
                gjRebars.SpacingType = TSM.BaseRebarGroup.RebarGroupSpacingTypeEnum.SPACING_TYPE_EXACT_SPACE_FLEX_AT_BOTH;
                gjRebars.StartHook.Shape = TSM.RebarHookData.RebarHookShapeEnum.CUSTOM_HOOK;
                gjRebars.StartHook.Angle = 135.0;
                gjRebars.StartHook.Radius = 2 * rebarSize;
                gjRebars.StartHook.Length = 5.0 * rebarSize;
                gjRebars.EndHook.Shape = TSM.RebarHookData.RebarHookShapeEnum.CUSTOM_HOOK;
                gjRebars.EndHook.Angle = 135.0;
                gjRebars.EndHook.Radius = 2 * rebarSize;
                gjRebars.EndHook.Length = 5.0 * rebarSize;


                gjRebars.StartPointOffsetValue = 0.0;
                gjRebars.EndPointOffsetValue = 0.0;
                gjRebars.StartPointOffsetType = TSM.Reinforcement.RebarOffsetTypeEnum.OFFSET_TYPE_COVER_THICKNESS;
                gjRebars.EndPointOffsetType = TSM.Reinforcement.RebarOffsetTypeEnum.OFFSET_TYPE_COVER_THICKNESS;

                gjRebars.Father = beam;

                gjRebars.Insert();


                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(currentPlane);
                model.CommitChanges();

            }
            catch (Exception)
            {
            }

        }

        private static T3D.CoordinateSystem BeamLocalCoord(TSM.Beam beam)
        {
            TSM.Model model = new TSM.Model();
            var currentPlane = model.GetWorkPlaneHandler().GetCurrentTransformationPlane();
            model.GetWorkPlaneHandler().SetCurrentTransformationPlane(new TSM.TransformationPlane());
            model.CommitChanges();

            beam.Select();

            //  var minPoint = beam.GetSolid().MinimumPoint;
            // var maxPoint = beam.GetSolid().MaximumPoint;

            var sPoint = beam.StartPoint;
            var ePoint = beam.EndPoint;

            T3D.Vector axisX = new T3D.Vector(ePoint - sPoint).GetNormal();
            T3D.Vector axisZ = new T3D.Vector(0, 0, 1);
            T3D.Vector axisY = axisZ.Cross(axisX);


            T3D.CoordinateSystem localCoord = new T3D.CoordinateSystem();
            localCoord.Origin = sPoint;
            localCoord.AxisX = axisX;
            localCoord.AxisY = axisY;

            model.GetWorkPlaneHandler().SetCurrentTransformationPlane(currentPlane);
            model.CommitChanges();

            return localCoord;
        }

        private static void Beam_LongRebar(TSM.Beam beam, T3D.CoordinateSystem localCoord)
        {
            try
            {
                TSM.Model model = new TSM.Model();
                var currentPlane = model.GetWorkPlaneHandler().GetCurrentTransformationPlane();
                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(new TSM.TransformationPlane());
                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(new TSM.TransformationPlane(localCoord));
                model.CommitChanges();
                beam.Select();

                //    double rebarSize = 20.0;
                double coverThick = 25.0;

                var minPoint = beam.GetSolid().MinimumPoint;
                var maxPoint = beam.GetSolid().MaximumPoint;

                var startP = beam.StartPoint;
                var endP = beam.EndPoint;

                double dx = maxPoint.X - minPoint.X; // 宽
                double dz = maxPoint.Z - minPoint.Z; // 高
                double dy = maxPoint.Y - minPoint.Y; // 长

                TSM.SingleRebar sRebar = new TSM.SingleRebar();

                sRebar.Class = 20;
                sRebar.Polygon = new TSM.Polygon();
                sRebar.Polygon.Points.Add(new T3D.Point(minPoint.X, maxPoint.Y - coverThick - 50.0, minPoint.Z + 150.0));
                sRebar.Polygon.Points.Add(new T3D.Point(minPoint.X + 50.0, maxPoint.Y - coverThick - 50.0, minPoint.Z + 150.0));
                sRebar.Polygon.Points.Add(new T3D.Point(minPoint.X + 50.0 + 750, maxPoint.Y - coverThick, minPoint.Z + coverThick));
                sRebar.Polygon.Points.Add(new T3D.Point(maxPoint.X - 50.0 - 750.0, maxPoint.Y - coverThick, minPoint.Z + coverThick));
                sRebar.Polygon.Points.Add(new T3D.Point(maxPoint.X - 50.0, maxPoint.Y - coverThick, minPoint.Z + 150.0));
                sRebar.Polygon.Points.Add(new T3D.Point(maxPoint.X, maxPoint.Y - coverThick, minPoint.Z + 150.0));

                sRebar.Grade = "HRB400";
                sRebar.RadiusValues = new System.Collections.ArrayList() { 40.0 };

                sRebar.Name = "R";
                sRebar.NumberingSeries = new TSM.NumberingSeries("R", 1);

                sRebar.Size = "20";


                sRebar.StartPointOffsetValue = -500.0;
                sRebar.EndPointOffsetValue = -500.0;
                sRebar.StartPointOffsetType = TSM.Reinforcement.RebarOffsetTypeEnum.OFFSET_TYPE_COVER_THICKNESS;
                sRebar.EndPointOffsetType = TSM.Reinforcement.RebarOffsetTypeEnum.OFFSET_TYPE_COVER_THICKNESS;

                sRebar.Father = beam;

                sRebar.Insert();

                model.GetWorkPlaneHandler().SetCurrentTransformationPlane(currentPlane);
                model.CommitChanges();
            }
            catch (Exception)
            {
            }
        }

    }
}
